<template>
  <view class="v-swiper">
    <swiper
      :style="{ height: height || '320rpx', width: width }"
      :circular="circular !== false"
      :autoplay="autoplay"
      :interval="interval"
      :duration="duration"
      :previous-margin="card ? '27rpx' : '0'"
      :next-margin="card ? '27rpx' : '0'"
      @change="change"
    >
      <swiper-item v-for="(item, index) in list" :key="index">
        <v-video
          v-if="item.isVideo"
          ref="itemRef"
          :custom-style="{
            height: height,
            width: width
          }"
          :src="item[videoKey]"
          play-btn-position="center"
        />
        <view
          v-else-if="card"
          class="card"
          :style="{
            transition: 'transform 0.3s',
            transform: `scale(${index === currentIndex ? 1 : 0.95})`
          }"
          @click="$emit('click', item)"
        >
          <v-image
            ref="itemRef"
            :custom-style="{
              height: '100%',
              width: '100%'
            }"
            mode="aspectFit"
            border-radius="32rpx"
            :src="item[imgKey]"
            :preview="preview"
          />
          <view v-if="type === 'mask'" class="footer">
            <view class="mask" :class="{ show: !!item.title }" />
            <view class="title">
              {{ item.title }}
            </view>
          </view>
        </view>
        <view v-else class="container" @click="$emit('click', item)">
          <v-image
            ref="itemRef"
            mode="aspectFit"
            :height="height"
            :width="width"
            :src="item[imgKey]"
            :preview="preview"
          />
          <view v-if="type === 'mask'" class="footer">
            <view class="mask" :class="{ show: !!item.title }" />
            <view class="title">
              {{ item.title }}
            </view>
          </view>
        </view>
      </swiper-item>
    </swiper>
    <view v-if="type === 'dot'" class="dot-list">
      <view
        v-for="(image, index) in list"
        :key="index"
        class="dot-item"
        :class="{ active: index === currentIndex }"
      />
    </view>
    <view v-else-if="type === 'count'" class="index-pad">
      {{ `${currentIndex + 1}/${total}` }}
    </view>
    <view
      v-else-if="type === 'mask'"
      class="mask-count"
      :class="{ 'card-count': card }"
    >
      {{ `${currentIndex + 1}/${total}` }}
    </view>
  </view>
</template>

<script setup lang="ts">
import type VImage from '@/components/v-image/v-image.vue';
import type VVideo from '@/components/v-video/v-video.vue';
const props = withDefaults(
  defineProps<{
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    list?: Record<string, any>[];
    imgKey?: string;
    videoKey?: string;
    autoplay?: boolean;
    circular?: boolean;
    preview?: boolean;
    type?: string;
    card?: boolean;
    height?: string;
    width?: string;
    interval?: number;
    duration?: number;
  }>(),
  {
    list: () => [],
    imgKey: 'src',
    videoKey: 'src',
    autoplay: true,
    circular: true,
    preview: false,
    type: 'dot',
    card: false,
    height: undefined,
    width: undefined,
    interval: 5000,
    duration: 500
  }
);

interface Emits {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  (event: 'click', val: any): void;
  (event: 'update:current', val: number): void;
}
const emits = defineEmits<Emits>();

// eslint-disable-next-line func-call-spacing
const itemRef = ref<
  (InstanceType<typeof VImage> | InstanceType<typeof VVideo>)[]
    >([]);

const list = toRef(props, 'list');

const currentIndex = ref<number>(0);
const total = ref<number>(0);
const change = (event: SwiperChangeEvent) => {
  currentIndex.value = event.detail.current;
  emits('update:current', currentIndex.value);

  if (!list.value) return;
  for (let i = 0; i < itemRef.value.length; i++) {
    const item = itemRef.value[i];
    if (i !== event.detail.current && list.value[i]?.isVideo) {
      const videoRef = item as InstanceType<typeof VVideo>;
      videoRef?.pause();
    }
  }
};

onMounted(() => {
  watch(
    list,
    (val) => {
      if (!val) return;
      currentIndex.value = 0;
      total.value = val.length;
    },
    { immediate: true }
  );
});
</script>

<style lang="scss" scoped>
.v-swiper {
  position: relative;
  height: fit-content;
  width: fit-content;
  .dot-list {
    position: absolute;
    bottom: 28rpx;
    left: 0;
    right: 0;
    pointer-events: none;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8rpx;
    .dot-item {
      height: 6rpx;
      width: 8rpx;
      background-color: #a2a7b1;
      transition:
        background-color 0.2s linear,
        width 0.2s linear;
      &.active {
        background-color: #ff2f3b;
        width: 24rpx;
      }
    }
  }
  .index-pad {
    position: absolute;
    right: 20rpx;
    bottom: 30rpx;
    height: 38rpx;
    line-height: 38rpx;
    width: 80rpx;
    border-radius: 100vw;
    color: white;
    font-size: 24rpx;
    text-align: center;
    background-color: rgba(0, 0, 0, 0.4);
    pointer-events: none;
  }
  .card {
    height: 100%;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 32rpx;
    overflow: hidden;
    .footer {
      border-radius: 0 0 32rpx 32rpx;
    }
  }
  .footer {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 100rpx;
    display: flex;
    align-items: center;
    padding: 0 24rpx;
    gap: 8rpx;
    overflow: hidden;
    .mask {
      position: absolute;
      top: 0;
      left: 0;
      bottom: 0;
      right: 0;
      background: linear-gradient(
        360deg,
        rgba(0, 0, 0, 0.6) 0%,
        rgba(0, 0, 0, 0) 100%
      );
      transition: opacity 0.3s;
      opacity: 0;
      &.show {
        opacity: 1;
      }
    }
    .title {
      position: relative;
      flex: 1;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      color: white;
    }
  }
}
.mask-count {
  position: absolute;
  width: fit-content;
  right: 20rpx;
  bottom: 30rpx;
  color: white;
  background-color: rgba(0, 0, 0, 0.5);
  padding: 0 12rpx;
  border-radius: 20rpx;
  height: 40rpx;
  line-height: 40rpx;
  z-index: 1;
  &.card-count {
    right: 90rpx;
    bottom: 37rpx;
    border-radius: 20rpx;
  }
}
</style>
